package org.dromara.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.PageUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.device.api.RemoteDeviceService;
import org.dromara.device.api.domain.vo.OrdinaryDeviceVo;
import org.dromara.patrol.api.RemotePatrolReportService;
import org.dromara.patrol.api.RemotePatrolSnapPlanService;
import org.dromara.patrol.api.RemotePatrolSubtaskCommonService;
import org.dromara.system.api.domain.vo.RemoteStoreVo;
import org.dromara.system.domain.*;
import org.dromara.system.domain.bo.SysStoreBo;
import org.dromara.system.domain.vo.SysStoreRequestVo;
import org.dromara.system.domain.vo.SysStoreVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.*;
import org.dromara.system.service.ISysStoreService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统管理-门店配置Service业务层处理
 *
 * @author LionLi
 * @date 2024-03-18
 */
@RequiredArgsConstructor
@Service
public class SysStoreServiceImpl implements ISysStoreService {

    private final SysStoreMapper baseMapper;


    private final SysStoreLabelMapper sysStoreLabelMapper;

    private final SysAreaMapper sysAreaMapper;

    private final SysUserStoreMapper sysUserStoreMapper;

    private final SysDeptStoreMapper sysDeptStoreMapper;


    private final SysUserAreaMapper sysUserAreaMapper;


    private final SysUserMapper sysUserMapper;

    private final SysUserDeviceMapper sysUserDeviceMapper;

    @DubboReference
    private RemoteDeviceService remoteDeviceService;
    @DubboReference
    private RemotePatrolReportService remotePatrolReportService;
    @DubboReference
    private RemotePatrolSnapPlanService remotePatrolSnapPlanService;
    @DubboReference
    private RemotePatrolSubtaskCommonService remotePatrolSubtaskCommonService;



    /**
     * 查询系统管理-门店配置
     */
    @Override
    public SysStoreVo queryById(Long storeId){
        SysStoreBo bo = new SysStoreBo();
        bo.setStoreId(storeId);
        SysStoreVo sysStoreVo = baseMapper.selectStoreList(bo).get(0);
        if (ObjectUtil.isNull(sysStoreVo)){
            throw  new ServiceException("门店不存在,门店id ： " + storeId);
        }
       this.buildDeviceInfoByStoreIds(Arrays.asList(sysStoreVo));
        //上级区域名称
        SysArea area = sysAreaMapper.selectOne(new LambdaQueryWrapper<SysArea>().eq(SysArea::getAreaId, sysStoreVo.getGroupId()));
        //获取该门店下的用户
        List<SysUserVo>   storeUsersList =  baseMapper.selectUserListByStoreId(Arrays.asList(sysStoreVo.getStoreId()));
        //获取联系人员名称
        Long storeManagerId = sysStoreVo.getStoreManagerId();
        if (ObjectUtil.isNotNull(storeManagerId)){
            SysUserVo sysUserVo = sysUserMapper.selectUserById(storeManagerId);
            if (ObjectUtil.isNotNull(sysUserVo)){
                sysStoreVo.setStoreManagerName(sysUserVo.getUserName());
            }
        }
        sysStoreVo.setUsers(storeUsersList);
        if (ObjectUtil.isNotNull(area)){
            String areaName = area.getAreaName();
            sysStoreVo.setGroupName(areaName);
        }
        return sysStoreVo;
    }

    /**
     * 查询系统管理-门店配置列表
     */
    @Override
    public TableDataInfo<SysStoreVo> queryPageList(SysStoreBo bo, PageQuery pageQuery) {
        TableDataInfo<SysStoreVo> tableDataInfo = new TableDataInfo<>();
         bo.setUserId(LoginHelper.getUserId());
        //获取当前用户存在的门店id
        List<SysStoreVo> vos = sysUserMapper.selectUserStoresListByUser(bo);
        if (CollectionUtils.isEmpty(vos)) {
            tableDataInfo.setTotal(vos.size());
            tableDataInfo.setRows(vos);
            return tableDataInfo;
        }
        //获取到区域id的集合
        List<Long> storeIds = vos.stream()
                .parallel()
                .map(SysStoreVo::getStoreId) // 提取areaId
                .distinct().collect(Collectors.toList());
        List<SysStoreVo>  stores = baseMapper.selectGroupNameList(storeIds);
        Map<Long, String> areaMap = stores.stream().collect(Collectors.toMap(SysStoreVo::getStoreId, SysStoreVo::getGroupName));
        vos.forEach(vo -> vo.setGroupName(areaMap.get(vo.getStoreId())));
        //构建门店下设备的信息
        List<SysStoreVo> sysStoreVos = this.buildDeviceInfoByStoreIds(vos, bo.getIsDevice());
        int total = sysStoreVos.size();
        if (ObjectUtil.isNotNull(pageQuery.getPageSize()) || ObjectUtil.isNotNull(pageQuery.getPageNum())) {
            sysStoreVos = PageUtils.getPageData(sysStoreVos, pageQuery.getPageNum() - 1, pageQuery.getPageSize());
        }
        tableDataInfo.setTotal(total);
        tableDataInfo.setRows(sysStoreVos);
        return tableDataInfo;
    }




    @Override
    public List<RemoteStoreVo> selectNamesByStoreList(List<Long> storeIds) {
        List<SysStore> sysStores = this.baseMapper.selectList(new LambdaQueryWrapper<>(SysStore.class)
                        .select(SysStore::getStoreId, SysStore::getStoreName)
                .in(SysStore::getStoreId, storeIds));
        if (CollUtil.isEmpty(sysStores)) {
            return CollUtil.newArrayList();
        }
        return BeanUtil.copyToList(sysStores, RemoteStoreVo.class);
    }

    /**
     * 根据店铺ID列表查询上级名称列表
     *
     * @param storeIds 店铺ID列表
     * @return 包含店铺名称的RemoteStoreVo对象列表
     */
    @Override
    public List<RemoteStoreVo> selectGroupNamesByStoreList(List<Long> storeIds) {
        if (CollUtil.isEmpty(storeIds)) {
            return CollUtil.newArrayList();
        }
        List<SysStoreVo> remoteStoreVos = this.baseMapper.selectGroupNameList(storeIds);
       //获取上级区域的id
        return BeanUtil.copyToList(remoteStoreVos, RemoteStoreVo.class);
    }

    /**
     * 通过门店ids获取设备信息
     * @param sysStoreVos
     * @param isDevice
     * @return
     */
    @Override
    public List<SysStoreVo> buildDeviceInfoByStoreIds(List<SysStoreVo> sysStoreVos, Boolean isDevice) {
        List<Long> storeIds = sysStoreVos.stream().
                map(SysStoreVo::getStoreId).
                collect(Collectors.toList());
        Map<Long, List<OrdinaryDeviceVo>> storeToDeviceVosMap = remoteDeviceService.
                queryByStoreIds(storeIds).stream().
                collect(Collectors.groupingBy(OrdinaryDeviceVo::getStoreId));

        //判断是不是admin用户
        if (!LoginHelper.isTenantAdmin() && !LoginHelper.isSuperAdmin()) {
            //获取当前管理用户的设备
            List<SysUserDevice> sysUserDevices = sysUserMapper.selectUserDeviceListByUser(Arrays.asList(LoginHelper.getUserId()));
            if (CollUtil.isNotEmpty(sysUserDevices)) {
                List<Long> deviceIds = sysUserDevices.stream().map(SysUserDevice::getDeviceId).collect(Collectors.toList());
                //过滤掉不在当前用户的设备
                storeToDeviceVosMap.replaceAll((storeId, deviceVos) -> {
                    return deviceVos.stream().filter(deviceVo ->
                            deviceIds.contains(deviceVo.getDeviceId())).collect(Collectors.toList());
                });
            }
        }
        for (SysStoreVo sysStoreVo : sysStoreVos) {
            Long storeId = sysStoreVo.getStoreId();
            List<OrdinaryDeviceVo> devices = storeToDeviceVosMap.getOrDefault(storeId, Collections.emptyList());
            sysStoreVo.setDevices(devices);
            sysStoreVo.setDeviceNum(devices.size());
            sysStoreVo.setOnlineDevice(devices.stream()
                    .filter(device -> "0".equals(device.getStatus()))
                    .count());
        }
        if (ObjectUtil.isNotNull(isDevice)) {
            if (isDevice) {
                //有设备
                sysStoreVos = sysStoreVos.stream()
                        .filter(sysStoreVo -> sysStoreVo.getDeviceNum() != 0)
                        .collect(Collectors.toList());
            } else {
                //没有设备
                sysStoreVos = sysStoreVos.stream()
                        .filter(sysStoreVo -> sysStoreVo.getDeviceNum() == 0)
                        .collect(Collectors.toList());
            }
        }
        return sysStoreVos;
    }


    /**
     * 通过门店ids获取设备信息
     * @param sysStoreVos
     * @return
     */
    @Override
    public List<SysStoreVo> buildDeviceInfoByStoreIds(List<SysStoreVo> sysStoreVos) {
        List<Long> storeIds = sysStoreVos.stream().
                map(SysStoreVo::getStoreId).
                collect(Collectors.toList());
        Map<Long, List<OrdinaryDeviceVo>> storeToDeviceVosMap = remoteDeviceService.
                queryByStoreIds(storeIds).stream().
                collect(Collectors.groupingBy(OrdinaryDeviceVo::getStoreId));

        //判断是不是admin用户
        if (!LoginHelper.isTenantAdmin() && !LoginHelper.isSuperAdmin()) {
            //获取当前管理用户的设备
            List<SysUserDevice> sysUserDevices = sysUserMapper.selectUserDeviceListByUser(Arrays.asList(LoginHelper.getUserId()));
            if (CollUtil.isNotEmpty(sysUserDevices)) {
                List<Long> deviceIds = sysUserDevices.stream().map(SysUserDevice::getDeviceId).collect(Collectors.toList());
                //过滤掉不在当前用户的设备
                storeToDeviceVosMap.replaceAll((storeId, deviceVos) -> {
                    return deviceVos.stream().filter(deviceVo ->
                            deviceIds.contains(deviceVo.getDeviceId())).collect(Collectors.toList());
                });
            }
        }
        for (SysStoreVo sysStoreVo : sysStoreVos) {
            Long storeId = sysStoreVo.getStoreId();
            List<OrdinaryDeviceVo> devices = storeToDeviceVosMap.getOrDefault(storeId, Collections.emptyList());
            sysStoreVo.setDevices(devices);
            sysStoreVo.setDeviceNum(devices.size());
            sysStoreVo.setOnlineDevice(devices.stream()
                    .filter(device -> "0".equals(device.getStatus()))
                    .count());
        }
        return sysStoreVos;
    }


    /**
     * 查询系统管理-门店配置列表
     */
    @Override
    public List<SysStoreVo> queryList(SysStoreBo bo) {
        QueryWrapper<SysStore> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private QueryWrapper<SysStore> buildQueryWrapper(SysStoreBo bo) {
        QueryWrapper<SysStore> lqw = new QueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(bo.getGroupIdStr()), "s.group_ids", "%" + bo.getGroupIdStr() + "%").
                eq(StringUtils.isNotBlank(bo.getStoreStatus()), "s.store_status", bo.getStoreStatus()).
                like(StringUtils.isNotBlank(bo.getStoreName()), "s.store_name", "%" + bo.getStoreName() + "%").
                eq(ObjectUtil.isNotNull(bo.getStoreId()), "s.store_id", bo.getStoreId());
        //校验当前用户是否是租户创建的admin账户
        if (!LoginHelper.isTenantAdmin() && !LoginHelper.isSuperAdmin()) {
            List<Long> storeIds = sysUserMapper.selectUserStoreIdListByUser(LoginHelper.getUserId());
            lqw.in("s.store_id", storeIds.toArray() != null ? storeIds : -1L);
        }
        return lqw;
    }

    /**
     * 新增系统管理-门店配置
     */
    @Override
    public Long insertByBo(SysStoreBo bo) {
       SysStore add = bo.toConvert(bo);
       //设置祖籍编码
        BuildGroupIds(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setStoreId(add.getStoreId());
            addStoreLabels(bo);
            addUserStore(bo);
        }else {
            throw new ServiceException("添加门店失败");
        }
        return add.getStoreId();
    }

    /**
     * 添加用户门店
     * @param bo
     */
    private void addUserStore(SysStoreBo bo) {
        //把在区域下的用户查询出来,然后添加用户的门店
        Long groupId = bo.getGroupId();
        LambdaQueryWrapper<SysUserArea> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserArea::getAreaId, groupId);
        List<SysUserArea> sysUserAreas = sysUserAreaMapper.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(sysUserAreas)) {
            //同一个区域下的用户
            List<Long> userIds = sysUserAreas.stream().distinct().
                    map(SysUserArea::getUserId).collect(Collectors.toList());

            //添加门店,只要有同一个区域的用户都有该门店
            List<SysUserStore> sysUserStores = userIds.stream()
                    .map(userId -> {
                        SysUserStore sysUserStore = new SysUserStore();
                        sysUserStore.setStoreId(bo.getStoreId());
                        sysUserStore.setUserId(userId);
                        return sysUserStore;
                    })
                    .collect(Collectors.toList());
            sysUserStoreMapper.insertBatch(sysUserStores);
        }

    }

    private void BuildGroupIds(SysStore store) {
        Long groupId = store.getGroupId();
        LambdaQueryWrapper<SysArea> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysArea::getAreaId, groupId);
        //父区域
        SysArea area = sysAreaMapper.selectOne(wrapper);
        String groupIds = groupId + StringUtils.SEPARATOR +area.getAncestors();
        store.setGroupIds(groupIds);

    }

    /**
     * 添加门店标签
     * @param bo
     */
    private void addStoreLabels(SysStoreBo bo) {
        LambdaQueryWrapper<SysStoreLabel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysStoreLabel::getStoreId, bo.getStoreId());
        sysStoreLabelMapper.delete(wrapper);
        List<String> storeLabels = bo.getStoreLabels();
        if (CollectionUtils.isEmpty(storeLabels)) {
            return;
        }
        List<SysStoreLabel> sysStoreLabels = storeLabels.stream()
                .map(storeLabel -> {
                    SysStoreLabel sysStoreLabel = new SysStoreLabel();
                    sysStoreLabel.setStoreId(bo.getStoreId());
                    sysStoreLabel.setLabelId(Long.parseLong(storeLabel));
                    return sysStoreLabel;
                })
                .collect(Collectors.toList());
        sysStoreLabelMapper.insertBatch(sysStoreLabels);
    }

    /**
     * 修改系统管理-门店配置
     */
    @Override
    public Boolean updateByBo(SysStoreBo bo) {
        SysStore update = bo.toConvert(bo);
        //设置祖籍编码
        BuildGroupIds(update);
        addStoreLabels(bo);
        return baseMapper.updateById(update) > 0;
    }


    /**
     * 检查门店编码是否存在
     *
     * @param bo
     */
    @Override
    public Boolean checkStoreCode(SysStoreBo bo) {
        long storeId = ObjectUtil.isNull(bo.getStoreId()) ? -1L : bo.getStoreId();
        SysStore store = baseMapper.selectOne(new LambdaQueryWrapper<SysStore>().eq(SysStore::getStoreCode, bo.getStoreCode()));
        if (ObjectUtil.isNotNull(store) && store.getStoreId() != storeId) {
            return false;
        }
        return true;
    }

    /**
     * 批量修改营业时间
     *
     * @param vo
     * @return
     */
    @Override
    public Boolean updateTime(SysStoreRequestVo vo) {
        List<SysStore> stores = vo.getStoreIds().stream().map(storeIds -> {
            SysStore store = new SysStore();
            store.setStoreId(storeIds.getStoreId());
            store.setBusinessTimeInfo(vo.getBusinessTimeInfo());
            return store;
        }).collect(Collectors.toList());
        return baseMapper.updateBatchById(stores);
    }

    /**
     * 删除门店
     *
     * @return
     */
    @Override
    @GlobalTransactional
    public Boolean deleteStoreById(Long storeId) {
       Boolean flag =  baseMapper.deleteById(storeId) > 0;
        if (flag) {
            //删除用户门店
            LambdaQueryWrapper<SysUserStore> userWrapper = new LambdaQueryWrapper<>();
            sysUserStoreMapper.delete(userWrapper.eq(SysUserStore::getStoreId, storeId));
            //删除部门门店;
            LambdaQueryWrapper<SysDeptStore> deptWrapper = new LambdaQueryWrapper<>();
            sysDeptStoreMapper.delete(deptWrapper.eq(SysDeptStore::getStoreId,storeId));
            //解绑设备
            unBindDevice(storeId);

        }
        return flag;
    }

    /**
     * 解绑设备
     * @param storeId
     */
    private void unBindDevice(Long storeId) {
         List<OrdinaryDeviceVo> deviceVos = remoteDeviceService.queryByStoreIds(Arrays.asList(storeId));
        if (CollectionUtils.isNotEmpty(deviceVos)){
            boolean flag = remoteDeviceService.unbindByStoreId(storeId);
            if (!flag) {
                throw new ServiceException("设备解绑异常");
            }
            //删除门店相关信息,有设备才有相关信息
            //1.删除报告
            remotePatrolReportService.deletePatrolReport(storeId);
            //2.删除抓拍配置
            remotePatrolSnapPlanService.deletePatrolSnapPlan(storeId);
            //3.删除任务列表 TODO
            remotePatrolSubtaskCommonService.deleteStoreLinkageHandleTask(storeId);

        }
    }

    /**
     * 根据门店id获取区域id
     *
     * @param storeId
     * @return
     */
    @Override
    public Long selectGroupIdByStoreId(Long storeId) {
        SysStore sysStore = baseMapper.selectById(storeId);
        if (ObjectUtil.isNull(sysStore)){
            throw new ServiceException("门店不存在");
        }
        return sysStore.getGroupId();
    }

    /**
     * 根据区域id集合获取门店信息
     * @param groupIds
     * @return
     */
    @Override
    public List<RemoteStoreVo> queryStoreByGroupIds(List<Long> groupIds) {
        if (CollectionUtils.isEmpty(groupIds)){
            throw new ServiceException("参数错误");
        }
        LambdaQueryWrapper<SysStore> wrapper = new LambdaQueryWrapper<>();
        List<Long> collect = groupIds.stream().distinct().collect(Collectors.toList());
        wrapper.in(SysStore::getGroupId,collect);
        wrapper.eq(SysStore::getDelFlag,"0");
        List<SysStore> sysStores = baseMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(sysStores)){
            return List.of();
        }
        return BeanUtil.copyToList(sysStores, RemoteStoreVo.class);
    }

    /**
     * 根据门店ids 查询门店是否存在
     *
     * @param storeIds
     * @return
     */
    @Override
    public Map<Long, Boolean> queryIsStore(List<Long> storeIds) {
        if (CollectionUtils.isEmpty(storeIds)){
            throw new ServiceException("参数错误");
        }
        // 创建一个Map来存储storeId和对应的查询结果
        Map<Long, Boolean> map = new HashMap<>();
        LambdaQueryWrapper<SysStore> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SysStore::getStoreId, storeIds);
        wrapper.eq(SysStore::getDelFlag, "0");
        List<SysStore> sysStores = baseMapper.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(storeIds)){
            List<Long> collect = sysStores.stream().map(SysStore::getStoreId).collect(Collectors.toList());
            storeIds.removeAll(collect);
            collect.forEach(storeId -> map.put(storeId,true));
        }
        // 将所有不在查询结果中的storeId添加到Map中，并设置value为false
        storeIds.forEach(storeId -> map.put(storeId,false));
        return map;
    }

    /**
     * 获取全部门店
     *
     * @return
     */
    @Override
    public List<RemoteStoreVo> queryStore() {
        LambdaQueryWrapper<SysStore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysStore::getDelFlag,"0");
        List<SysStore> sysStores = baseMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(sysStores)){
            return Arrays.asList();
        }
        return BeanUtil.copyToList(sysStores, RemoteStoreVo.class);
    }
}
